/**
 * @file socket_example.cpp
 * @brief TCP套接字示例程序
 * @details 演示如何使用TCP服务器和客户端进行通信
 */

#include "time_utils.h"
#include "logging.h"
#include "tcp_server.h"

/**
 * @brief 主函数
 * @details 创建TCP服务器和多个客户端，并演示它们之间的通信
 * @return 程序退出码，0表示成功
 */
int main(int, char **) {
  using namespace Common;

  /**
   * @brief 时间字符串缓存
   */
  std::string time_str_;
  
  /**
   * @brief 日志对象
   * @details 用于记录程序运行日志，输出到socket_example.log文件
   */
  Logger logger_("socket_example.log");

  /**
   * @brief TCP服务器接收数据的回调函数
   * @details 当服务器接收到客户端数据时调用，将数据记录到日志并发送回复
   * @param socket 接收数据的套接字
   * @param rx_time 接收数据的时间戳
   */
  auto tcpServerRecvCallback = [&](TCPSocket *socket, Nanos rx_time) noexcept {
    logger_.log("TCPServer::defaultRecvCallback() socket:% len:% rx:%\n",
                socket->socket_fd_, socket->next_rcv_valid_index_, rx_time);

    const std::string reply = "TCPServer received msg:" + std::string(socket->inbound_data_.data(), socket->next_rcv_valid_index_);
    socket->next_rcv_valid_index_ = 0;

    socket->send(reply.data(), reply.length());
  };

  /**
   * @brief TCP服务器接收数据完成的回调函数
   * @details 当服务器完成所有数据的接收和处理后调用
   */
  auto tcpServerRecvFinishedCallback = [&]() noexcept {
    logger_.log("TCPServer::defaultRecvFinishedCallback()\n");
  };

  /**
   * @brief TCP客户端接收数据的回调函数
   * @details 当客户端接收到服务器数据时调用，将数据记录到日志
   * @param socket 接收数据的套接字
   * @param rx_time 接收数据的时间戳
   */
  auto tcpClientRecvCallback = [&](TCPSocket *socket, Nanos rx_time) noexcept {
    const std::string recv_msg = std::string(socket->inbound_data_.data(), socket->next_rcv_valid_index_);
    socket->next_rcv_valid_index_ = 0;

    logger_.log("TCPSocket::defaultRecvCallback() socket:% len:% rx:% msg:%\n",
                socket->socket_fd_, socket->next_rcv_valid_index_, rx_time, recv_msg);
  };

  /**
   * @brief 网络接口名称
   * @details 使用本地回环接口
   */
  const std::string iface = "lo";
  
  /**
   * @brief IP地址
   * @details 使用本地回环地址127.0.0.1
   */
  const std::string ip = "127.0.0.1";
  
  /**
   * @brief 端口号
   * @details 使用端口12345进行通信
   */
  const int port = 12345;

  // 创建TCP服务器并设置回调函数
  logger_.log("Creating TCPServer on iface:% port:%\n", iface, port);
  TCPServer server(logger_);
  server.recv_callback_ = tcpServerRecvCallback;
  server.recv_finished_callback_ = tcpServerRecvFinishedCallback;
  server.listen(iface, port);

  /**
   * @brief 客户端套接字容器
   * @details 创建5个客户端进行测试
   */
  std::vector<TCPSocket *> clients(5);

  // 创建并连接多个客户端
  for (size_t i = 0; i < clients.size(); ++i) {
    // 创建新的客户端套接字并设置回调
    clients[i] = new TCPSocket(logger_);
    clients[i]->recv_callback_ = tcpClientRecvCallback;

    // 连接到服务器
    logger_.log("Connecting TCPClient-[%] on ip:% iface:% port:%\n", i, ip, iface, port);
    clients[i]->connect(ip, iface, port, false);
    // 检查服务器是否有新连接
    server.poll();
  }

  // 引入时间字面量命名空间
  using namespace std::literals::chrono_literals;

  // 进行5轮测试，每轮所有客户端都发送消息
  for (auto itr = 0; itr < 5; ++itr) {
    for (size_t i = 0; i < clients.size(); ++i) {
      // 构造客户端发送的消息
      const std::string client_msg = "CLIENT-[" + std::to_string(i) + "] : Sending " + std::to_string(itr * 100 + i);
      logger_.log("Sending TCPClient-[%] %\n", i, client_msg);
      // 发送消息并检查响应
      clients[i]->send(client_msg.data(), client_msg.length());
      clients[i]->sendAndRecv();

      // 等待500毫秒，然后检查服务器状态并处理数据
      std::this_thread::sleep_for(500ms);
      server.poll();
      server.sendAndRecv();
    }
  }

  // 程序成功返回
  return 0;
}
